home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume24 / gnucalc / part04 < prev    next >
Encoding:
Text File  |  1991-10-28  |  55.3 KB  |  1,708 lines

  1. Newsgroups: comp.sources.misc
  2. From: daveg@synaptics.com (David Gillespie)
  3. Subject:  v24i052:  gnucalc - GNU Emacs Calculator, v2.00, Part04/56
  4. Message-ID: <1991Oct29.042344.7119@sparky.imd.sterling.com>
  5. X-Md4-Signature: 79cbb6bf72e1a8e06e57c51a7af51d63
  6. Date: Tue, 29 Oct 1991 04:23:44 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: daveg@synaptics.com (David Gillespie)
  10. Posting-number: Volume 24, Issue 52
  11. Archive-name: gnucalc/part04
  12. Environment: Emacs
  13. Supersedes: gmcalc: Volume 13, Issue 27-45
  14.  
  15. ---- Cut Here and unpack ----
  16. #!/bin/sh
  17. # this is Part.04 (part 4 of a multipart archive)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file calc-aent.el continued
  20. #
  21. if test ! -r _shar_seq_.tmp; then
  22.     echo 'Please unpack part 1 first!'
  23.     exit 1
  24. fi
  25. (read Scheck
  26.  if test "$Scheck" != 4; then
  27.     echo Please unpack part "$Scheck" next!
  28.     exit 1
  29.  else
  30.     exit 0
  31.  fi
  32. ) < _shar_seq_.tmp || exit 1
  33. if test ! -f _shar_wnt_.tmp; then
  34.     echo 'x - still skipping calc-aent.el'
  35. else
  36. echo 'x - continuing file calc-aent.el'
  37. sed 's/^X//' << 'SHAR_EOF' >> 'calc-aent.el' &&
  38. X           exp-data (upcase (math-match-substring exp-str 0))
  39. X           exp-pos (match-end 0)))
  40. X        ((and (eq calc-language 'math)
  41. X          (eq (string-match "\\[\\[\\|->\\|:>" exp-str exp-pos)
  42. X              exp-pos))
  43. X         (setq exp-token 'punc
  44. X           exp-data (math-match-substring exp-str 0)
  45. X           exp-pos (match-end 0)))
  46. X        ((and (eq calc-language 'eqn)
  47. X          (eq (string-match "->\\|<-\\|+-\\|\\\\dots\\|~\\|\\^"
  48. X                    exp-str exp-pos)
  49. X              exp-pos))
  50. X         (setq exp-token 'punc
  51. X           exp-data (math-match-substring exp-str 0)
  52. X           exp-pos (match-end 0))
  53. X         (and (eq (string-match "\\\\dots\\." exp-str exp-pos) exp-pos)
  54. X          (setq exp-pos (match-end 0)))
  55. X         (if (memq (aref exp-data 0) '(?~ ?^))
  56. X         (math-read-token)))
  57. X        ((eq (string-match "%%.*$" exp-str exp-pos) exp-pos)
  58. X         (setq exp-pos (match-end 0))
  59. X         (math-read-token))
  60. X        (t
  61. X         (if (and (eq ch ?\{) (memq calc-language '(tex eqn)))
  62. X         (setq ch ?\())
  63. X         (if (and (eq ch ?\}) (memq calc-language '(tex eqn)))
  64. X         (setq ch ?\)))
  65. X         (if (and (eq ch ?\&) (eq calc-language 'tex))
  66. X         (setq ch ?\,))
  67. X         (setq exp-token 'punc
  68. X           exp-data (char-to-string ch)
  69. X           exp-pos (1+ exp-pos))))))
  70. )
  71. X
  72. X
  73. (defun math-read-expr-level (exp-prec)
  74. X  (let* ((x (math-read-factor)) (first t) op op2)
  75. X    (while (and (or (and (setq op (assoc exp-data math-expr-opers))
  76. X             (/= (nth 2 op) -1)
  77. X             (or (and (setq op2 (assoc
  78. X                         exp-data
  79. X                         (cdr (memq op math-expr-opers))))
  80. X                  (eq (= (nth 3 op) -1)
  81. X                      (/= (nth 3 op2) -1))
  82. X                  (eq (= (nth 3 op2) -1)
  83. X                      (not (math-factor-after)))
  84. X                  (setq op op2))
  85. X                 t))
  86. X            (and (or (eq (nth 2 op) -1)
  87. X                 (memq exp-token '(symbol number dollar hash))
  88. X                 (equal exp-data "(")
  89. X                 (and (equal exp-data "[")
  90. X                  (not (eq calc-language 'math))
  91. X                  (not (and exp-keep-spaces
  92. X                        (eq (car-safe x) 'vec)))))
  93. X             (setq op (assoc "2x" math-expr-opers))))
  94. X        (>= (nth 2 op) exp-prec))
  95. X      (if (not (equal (car op) "2x"))
  96. X      (math-read-token))
  97. X      (and (memq (nth 1 op) '(sdev mod))
  98. X       (calc-extensions))
  99. X      (setq x (cond ((consp (nth 1 op))
  100. X             (funcall (car (nth 1 op)) x op))
  101. X            ((eq (nth 3 op) -1)
  102. X             (if (eq (nth 1 op) 'ident)
  103. X             x
  104. X               (if (eq (nth 1 op) 'closing)
  105. X               (if (eq (nth 2 op) exp-prec)
  106. X                   (progn
  107. X                 (setq exp-prec 1000)
  108. X                 x)
  109. X                 (throw 'syntax "Mismatched delimiters"))
  110. X             (list (nth 1 op) x))))
  111. X            ((and (not first)
  112. X              (memq (nth 1 op) math-alg-inequalities)
  113. X              (memq (car-safe x) math-alg-inequalities))
  114. X             (calc-extensions)
  115. X             (math-composite-inequalities x op))
  116. X            (t (list (nth 1 op)
  117. X                 x
  118. X                 (math-read-expr-level (nth 3 op)))))
  119. X        first nil))
  120. X    x)
  121. )
  122. X
  123. (defconst math-alg-inequalities
  124. X  '(calcFunc-lt calcFunc-gt calcFunc-leq calcFunc-geq
  125. X        calcFunc-eq calcFunc-neq))
  126. X
  127. (defun math-remove-dashes (x)
  128. X  (if (string-match "\\`\\(.*\\)-\\(.*\\)\\'" x)
  129. X      (math-remove-dashes
  130. X       (concat (math-match-substring x 1) "#" (math-match-substring x 2)))
  131. X    x)
  132. )
  133. X
  134. (defun math-restore-dashes (x)
  135. X  (if (string-match "\\`\\(.*\\)[#_]\\(.*\\)\\'" x)
  136. X      (math-restore-dashes
  137. X       (concat (math-match-substring x 1) "-" (math-match-substring x 2)))
  138. X    x)
  139. )
  140. X
  141. (defun math-read-if (cond op)
  142. X  (let ((then (math-read-expr-level 0)))
  143. X    (or (equal exp-data ":")
  144. X    (throw 'syntax "Expected ':'"))
  145. X    (math-read-token)
  146. X    (list 'calcFunc-if cond then (math-read-expr-level (nth 3 op))))
  147. )
  148. X
  149. (defun math-factor-after ()
  150. X  (let ((exp-pos exp-pos)
  151. X    exp-old-pos exp-token exp-data)
  152. X    (math-read-token)
  153. X    (or (memq exp-token '(number symbol dollar hash string))
  154. X    (and (assoc exp-data '(("-") ("+") ("!") ("|") ("/")))
  155. X         (assoc (concat "u" exp-data) math-expr-opers))
  156. X    (eq (nth 2 (assoc exp-data math-expr-opers)) -1)
  157. X    (assoc exp-data '(("(") ("[") ("{")))))
  158. )
  159. X
  160. (defun math-read-factor ()
  161. X  (let (op)
  162. X    (cond ((eq exp-token 'number)
  163. X       (let ((num (math-read-number exp-data)))
  164. X         (if (not num)
  165. X         (progn
  166. X           (setq exp-old-pos exp-pos)
  167. X           (throw 'syntax "Bad format")))
  168. X         (math-read-token)
  169. X         (if (and math-read-expr-quotes
  170. X              (consp num))
  171. X         (list 'quote num)
  172. X           num)))
  173. X      ((or (equal exp-data "-")
  174. X           (equal exp-data "+")
  175. X           (equal exp-data "!")
  176. X           (equal exp-data "|")
  177. X           (equal exp-data "/"))
  178. X       (setq exp-data (concat "u" exp-data))
  179. X       (math-read-factor))
  180. X      ((and (setq op (assoc exp-data math-expr-opers))
  181. X        (eq (nth 2 op) -1))
  182. X       (if (consp (nth 1 op))
  183. X           (funcall (car (nth 1 op)) op)
  184. X         (math-read-token)
  185. X         (let ((val (math-read-expr-level (nth 3 op))))
  186. X           (cond ((eq (nth 1 op) 'ident)
  187. X              val)
  188. X             ((and (Math-numberp val)
  189. X               (equal (car op) "u-"))
  190. X              (math-neg val))
  191. X             (t (list (nth 1 op) val))))))
  192. X      ((eq exp-token 'symbol)
  193. X       (let ((sym (intern exp-data)))
  194. X         (math-read-token)
  195. X         (if (equal exp-data calc-function-open)
  196. X         (let ((f (assq sym math-expr-function-mapping)))
  197. X           (math-read-token)
  198. X           (if (consp (cdr f))
  199. X               (funcall (car (cdr f)) f sym)
  200. X             (let ((args (if (or (equal exp-data calc-function-close)
  201. X                     (eq exp-token 'end))
  202. X                     nil
  203. X                   (math-read-expr-list))))
  204. X               (if (not (or (equal exp-data calc-function-close)
  205. X                    (eq exp-token 'end)))
  206. X               (throw 'syntax "Expected `)'"))
  207. X               (math-read-token)
  208. X               (if f
  209. X               (setq sym (cdr f))
  210. X             (and (= (aref (symbol-name sym) 0) ?\\)
  211. X                  (< (prefix-numeric-value calc-language-option) 0)
  212. X                  (setq sym (intern (substring (symbol-name sym)
  213. X                               1))))
  214. X             (or (string-match "-" (symbol-name sym))
  215. X                 (setq sym (intern (concat "calcFunc-"
  216. X                               (symbol-name sym))))))
  217. X               (cons sym args))))
  218. X           (if math-read-expr-quotes
  219. X           sym
  220. X         (let ((val (list 'var
  221. X                  (intern (math-remove-dashes
  222. X                       (symbol-name sym)))
  223. X                  (if (string-match "-" (symbol-name sym))
  224. X                      sym
  225. X                    (intern (concat "var-"
  226. X                            (symbol-name sym)))))))
  227. X           (let ((v (assq (nth 1 val) math-expr-variable-mapping)))
  228. X             (and v (setq val (if (consp (cdr v))
  229. X                      (funcall (car (cdr v)) v val)
  230. X                    (list 'var
  231. X                          (intern
  232. X                           (substring (symbol-name (cdr v))
  233. X                              4))
  234. X                          (cdr v))))))
  235. X           (while (and (memq calc-language '(c pascal maple))
  236. X                   (equal exp-data "["))
  237. X             (math-read-token)
  238. X             (setq val (append (list 'calcFunc-subscr val)
  239. X                       (math-read-expr-list)))
  240. X             (if (equal exp-data "]")
  241. X             (math-read-token)
  242. X               (throw 'syntax "Expected ']'")))
  243. X           val)))))
  244. X      ((eq exp-token 'dollar)
  245. X       (if (>= (length calc-dollar-values) (math-abs exp-data))
  246. X           (let ((num exp-data))
  247. X         (math-read-token)
  248. X         (setq calc-dollar-used (max calc-dollar-used num))
  249. X         (math-check-complete (nth (1- (math-abs num))
  250. X                       calc-dollar-values)))
  251. X         (throw 'syntax (if calc-dollar-values
  252. X                "Too many $'s"
  253. X                  "$'s not allowed in this context"))))
  254. X      ((eq exp-token 'hash)
  255. X       (or calc-hashes-used
  256. X           (throw 'syntax "#'s not allowed in this context"))
  257. X       (calc-extensions)
  258. X       (if (<= exp-data (length calc-arg-values))
  259. X           (let ((num exp-data))
  260. X         (math-read-token)
  261. X         (setq calc-hashes-used (max calc-hashes-used num))
  262. X         (nth (1- num) calc-arg-values))
  263. X         (throw 'syntax "Too many # arguments")))
  264. X      ((equal exp-data "(")
  265. X       (let* ((exp (let ((exp-keep-spaces nil))
  266. X             (math-read-token)
  267. X             (if (or (equal exp-data "\\dots")
  268. X                 (equal exp-data "\\ldots"))
  269. X                 '(neg (var inf var-inf))
  270. X               (math-read-expr-level 0)))))
  271. X         (let ((exp-keep-spaces nil))
  272. X           (cond
  273. X        ((equal exp-data ",")
  274. X         (progn
  275. X           (math-read-token)
  276. X           (let ((exp2 (math-read-expr-level 0)))
  277. X             (setq exp
  278. X               (if (and exp2 (Math-realp exp) (Math-realp exp2))
  279. X                   (math-normalize (list 'cplx exp exp2))
  280. X                 (list '+ exp (list '* exp2 '(var i var-i))))))))
  281. X        ((equal exp-data ";")
  282. X         (progn
  283. X           (math-read-token)
  284. X           (let ((exp2 (math-read-expr-level 0)))
  285. X             (setq exp (if (and exp2 (Math-realp exp)
  286. X                    (Math-anglep exp2))
  287. X                   (math-normalize (list 'polar exp exp2))
  288. X                 (calc-extensions)
  289. X                 (list '* exp
  290. X                       (list 'calcFunc-exp
  291. X                         (list '*
  292. X                           (math-to-radians-2 exp2)
  293. X                           '(var i var-i)))))))))
  294. X        ((or (equal exp-data "\\dots")
  295. X             (equal exp-data "\\ldots"))
  296. X         (progn
  297. X           (math-read-token)
  298. X           (let ((exp2 (if (or (equal exp-data ")")
  299. X                       (equal exp-data "]")
  300. X                       (eq exp-token 'end))
  301. X                   '(var inf var-inf)
  302. X                 (math-read-expr-level 0))))
  303. X             (setq exp
  304. X               (list 'intv
  305. X                 (if (equal exp-data ")") 0 1)
  306. X                 exp
  307. X                 exp2)))))))
  308. X         (if (not (or (equal exp-data ")")
  309. X              (and (equal exp-data "]") (eq (car-safe exp) 'intv))
  310. X              (eq exp-token 'end)))
  311. X         (throw 'syntax "Expected `)'"))
  312. X         (math-read-token)
  313. X         exp))
  314. X      ((eq exp-token 'string)
  315. X       (calc-extensions)
  316. X       (math-read-string))
  317. X      ((equal exp-data "[")
  318. X       (calc-extensions)
  319. X       (math-read-brackets t "]"))
  320. X      ((equal exp-data "{")
  321. X       (calc-extensions)
  322. X       (math-read-brackets nil "}"))
  323. X      ((equal exp-data "<")
  324. X       (calc-extensions)
  325. X       (math-read-angle-brackets))
  326. X      (t (throw 'syntax "Expected a number"))))
  327. )
  328. X
  329. X
  330. X
  331. SHAR_EOF
  332. echo 'File calc-aent.el is complete' &&
  333. chmod 0644 calc-aent.el ||
  334. echo 'restore of calc-aent.el failed'
  335. Wc_c="`wc -c < 'calc-aent.el'`"
  336. test 28616 -eq "$Wc_c" ||
  337.     echo 'calc-aent.el: original size 28616, current size' "$Wc_c"
  338. rm -f _shar_wnt_.tmp
  339. fi
  340. # ============= calc-alg-2.el ==============
  341. if test -f 'calc-alg-2.el' -a X"$1" != X"-c"; then
  342.     echo 'x - skipping calc-alg-2.el (File already exists)'
  343.     rm -f _shar_wnt_.tmp
  344. else
  345. > _shar_wnt_.tmp
  346. echo 'x - extracting calc-alg-2.el (Text)'
  347. sed 's/^X//' << 'SHAR_EOF' > 'calc-alg-2.el' &&
  348. ;; Calculator for GNU Emacs, part II [calc-alg-2.el]
  349. ;; Copyright (C) 1990, 1991 Free Software Foundation, Inc.
  350. ;; Written by Dave Gillespie, daveg@csvax.cs.caltech.edu.
  351. X
  352. ;; This file is part of GNU Emacs.
  353. X
  354. ;; GNU Emacs is distributed in the hope that it will be useful,
  355. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  356. ;; accepts responsibility to anyone for the consequences of using it
  357. ;; or for whether it serves any particular purpose or works at all,
  358. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  359. ;; License for full details.
  360. X
  361. ;; Everyone is granted permission to copy, modify and redistribute
  362. ;; GNU Emacs, but only under the conditions described in the
  363. ;; GNU Emacs General Public License.   A copy of this license is
  364. ;; supposed to have been given to you along with GNU Emacs so you
  365. ;; can know your rights and responsibilities.  It should be in a
  366. ;; file named COPYING.  Among other things, the copyright notice
  367. ;; and this notice must be preserved on all copies.
  368. X
  369. X
  370. X
  371. ;; This file is autoloaded from calc-ext.el.
  372. (require 'calc-ext)
  373. X
  374. (require 'calc-macs)
  375. X
  376. (defun calc-Need-calc-alg-2 () nil)
  377. X
  378. X
  379. (defun calc-derivative (var num)
  380. X  (interactive "sDifferentiate with respect to: \np")
  381. X  (calc-slow-wrapper
  382. X   (and (< num 0) (error "Order of derivative must be positive"))
  383. X   (let ((func (if (calc-is-hyperbolic) 'calcFunc-tderiv 'calcFunc-deriv))
  384. X     n expr)
  385. X     (if (or (equal var "") (equal var "$"))
  386. X     (setq n 2
  387. X           expr (calc-top-n 2)
  388. X           var (calc-top-n 1))
  389. X       (setq var (math-read-expr var))
  390. X       (if (eq (car-safe var) 'error)
  391. X       (error "Bad format in expression: %s" (nth 1 var)))
  392. X       (setq n 1
  393. X         expr (calc-top-n 1)))
  394. X     (while (>= (setq num (1- num)) 0)
  395. X       (setq expr (list func expr var)))
  396. X     (calc-enter-result n "derv" expr)))
  397. )
  398. X
  399. (defun calc-integral (var)
  400. X  (interactive "sIntegration variable: ")
  401. X  (calc-slow-wrapper
  402. X   (if (or (equal var "") (equal var "$"))
  403. X       (calc-enter-result 2 "intg" (list 'calcFunc-integ
  404. X                     (calc-top-n 2)
  405. X                     (calc-top-n 1)))
  406. X     (let ((var (math-read-expr var)))
  407. X       (if (eq (car-safe var) 'error)
  408. X       (error "Bad format in expression: %s" (nth 1 var)))
  409. X       (calc-enter-result 1 "intg" (list 'calcFunc-integ
  410. X                     (calc-top-n 1)
  411. X                     var)))))
  412. )
  413. X
  414. (defun calc-num-integral (&optional varname lowname highname)
  415. X  (interactive "sIntegration variable: ")
  416. X  (calc-tabular-command 'calcFunc-ninteg "Integration" "nint"
  417. X            nil varname lowname highname)
  418. )
  419. X
  420. (defun calc-summation (arg &optional varname lowname highname)
  421. X  (interactive "P\nsSummation variable: ")
  422. X  (calc-tabular-command 'calcFunc-sum "Summation" "sum"
  423. X            arg varname lowname highname)
  424. )
  425. X
  426. (defun calc-alt-summation (arg &optional varname lowname highname)
  427. X  (interactive "P\nsSummation variable: ")
  428. X  (calc-tabular-command 'calcFunc-asum "Summation" "asum"
  429. X            arg varname lowname highname)
  430. )
  431. X
  432. (defun calc-product (arg &optional varname lowname highname)
  433. X  (interactive "P\nsIndex variable: ")
  434. X  (calc-tabular-command 'calcFunc-prod "Index" "prod"
  435. X            arg varname lowname highname)
  436. )
  437. X
  438. (defun calc-tabulate (arg &optional varname lowname highname)
  439. X  (interactive "P\nsIndex variable: ")
  440. X  (calc-tabular-command 'calcFunc-table "Index" "tabl"
  441. X            arg varname lowname highname)
  442. )
  443. X
  444. (defun calc-tabular-command (func prompt prefix arg varname lowname highname)
  445. X  (calc-slow-wrapper
  446. X   (let (var (low nil) (high nil) (step nil) stepname stepnum (num 1) expr)
  447. X     (if (consp arg)
  448. X     (setq stepnum 1)
  449. X       (setq stepnum 0))
  450. X     (if (or (equal varname "") (equal varname "$") (null varname))
  451. X     (setq high (calc-top-n (+ stepnum 1))
  452. X           low (calc-top-n (+ stepnum 2))
  453. X           var (calc-top-n (+ stepnum 3))
  454. X           num (+ stepnum 4))
  455. X       (setq var (if (stringp varname) (math-read-expr varname) varname))
  456. X       (if (eq (car-safe var) 'error)
  457. X       (error "Bad format in expression: %s" (nth 1 var)))
  458. X       (or lowname
  459. X       (setq lowname (read-string (concat prompt " variable: " varname
  460. X                          ", from: "))))
  461. X       (if (or (equal lowname "") (equal lowname "$"))
  462. X       (setq high (calc-top-n (+ stepnum 1))
  463. X         low (calc-top-n (+ stepnum 2))
  464. X         num (+ stepnum 3))
  465. X     (setq low (if (stringp lowname) (math-read-expr lowname) lowname))
  466. X     (if (eq (car-safe low) 'error)
  467. X         (error "Bad format in expression: %s" (nth 1 low)))
  468. X     (or highname
  469. X         (setq highname (read-string (concat prompt " variable: " varname
  470. X                         ", from: " lowname
  471. X                         ", to: "))))
  472. X     (if (or (equal highname "") (equal highname "$"))
  473. X         (setq high (calc-top-n (+ stepnum 1))
  474. X           num (+ stepnum 2))
  475. X       (setq high (if (stringp highname) (math-read-expr highname)
  476. X            highname))
  477. X       (if (eq (car-safe high) 'error)
  478. X           (error "Bad format in expression: %s" (nth 1 high)))
  479. X       (if (consp arg)
  480. X           (progn
  481. X         (setq stepname (read-string (concat prompt " variable: "
  482. X                             varname
  483. X                             ", from: " lowname
  484. X                             ", to: " highname
  485. X                             ", step: ")))
  486. X         (if (or (equal stepname "") (equal stepname "$"))
  487. X             (setq step (calc-top-n 1)
  488. X               num 2)
  489. X           (setq step (math-read-expr stepname))
  490. X           (if (eq (car-safe step) 'error)
  491. X               (error "Bad format in expression: %s"
  492. X                  (nth 1 step)))))))))
  493. X     (or step
  494. X     (if (consp arg)
  495. X         (setq step (calc-top-n 1))
  496. X       (if arg
  497. X           (setq step (prefix-numeric-value arg)))))
  498. X     (setq expr (calc-top-n num))
  499. X     (calc-enter-result num prefix (append (list func expr var low high)
  500. X                       (and step (list step))))))
  501. )
  502. X
  503. (defun calc-solve-for (var)
  504. X  (interactive "sVariable to solve for: ")
  505. X  (calc-slow-wrapper
  506. X   (let ((func (if (calc-is-inverse)
  507. X           (if (calc-is-hyperbolic) 'calcFunc-ffinv 'calcFunc-finv)
  508. X         (if (calc-is-hyperbolic) 'calcFunc-fsolve 'calcFunc-solve))))
  509. X     (if (or (equal var "") (equal var "$"))
  510. X     (calc-enter-result 2 "solv" (list func
  511. X                       (calc-top-n 2)
  512. X                       (calc-top-n 1)))
  513. X       (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
  514. X               (not (string-match "\\[" var)))
  515. X              (math-read-expr (concat "[" var "]"))
  516. X            (math-read-expr var))))
  517. X     (if (eq (car-safe var) 'error)
  518. X         (error "Bad format in expression: %s" (nth 1 var)))
  519. X     (calc-enter-result 1 "solv" (list func
  520. X                       (calc-top-n 1)
  521. X                       var))))))
  522. )
  523. X
  524. (defun calc-poly-roots (var)
  525. X  (interactive "sVariable to solve for: ")
  526. X  (calc-slow-wrapper
  527. X   (if (or (equal var "") (equal var "$"))
  528. X       (calc-enter-result 2 "prts" (list 'calcFunc-roots
  529. X                     (calc-top-n 2)
  530. X                     (calc-top-n 1)))
  531. X     (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
  532. X             (not (string-match "\\[" var)))
  533. X            (math-read-expr (concat "[" var "]"))
  534. X          (math-read-expr var))))
  535. X       (if (eq (car-safe var) 'error)
  536. X       (error "Bad format in expression: %s" (nth 1 var)))
  537. X       (calc-enter-result 1 "prts" (list 'calcFunc-roots
  538. X                     (calc-top-n 1)
  539. X                     var)))))
  540. )
  541. X
  542. (defun calc-taylor (var nterms)
  543. X  (interactive "sTaylor expansion variable: \nNNumber of terms: ")
  544. X  (calc-slow-wrapper
  545. X   (let ((var (math-read-expr var)))
  546. X     (if (eq (car-safe var) 'error)
  547. X     (error "Bad format in expression: %s" (nth 1 var)))
  548. X     (calc-enter-result 1 "tylr" (list 'calcFunc-taylor
  549. X                       (calc-top-n 1)
  550. X                       var
  551. X                       (prefix-numeric-value nterms)))))
  552. )
  553. X
  554. X
  555. (defun math-derivative (expr)   ; uses global values: deriv-var, deriv-total.
  556. X  (cond ((equal expr deriv-var)
  557. X     1)
  558. X    ((or (Math-scalarp expr)
  559. X         (eq (car expr) 'sdev)
  560. X         (and (eq (car expr) 'var)
  561. X          (or (not deriv-total)
  562. X              (math-const-var expr)
  563. X              (progn
  564. X            (math-setup-declarations)
  565. X            (memq 'const (nth 1 (or (assq (nth 2 expr)
  566. X                              math-decls-cache)
  567. X                        math-decls-all)))))))
  568. X     0)
  569. X    ((eq (car expr) '+)
  570. X     (math-add (math-derivative (nth 1 expr))
  571. X           (math-derivative (nth 2 expr))))
  572. X    ((eq (car expr) '-)
  573. X     (math-sub (math-derivative (nth 1 expr))
  574. X           (math-derivative (nth 2 expr))))
  575. X    ((memq (car expr) '(calcFunc-eq calcFunc-neq calcFunc-lt
  576. X                    calcFunc-gt calcFunc-leq calcFunc-geq))
  577. X     (list (car expr)
  578. X           (math-derivative (nth 1 expr))
  579. X           (math-derivative (nth 2 expr))))
  580. X    ((eq (car expr) 'neg)
  581. X     (math-neg (math-derivative (nth 1 expr))))
  582. X    ((eq (car expr) '*)
  583. X     (math-add (math-mul (nth 2 expr)
  584. X                 (math-derivative (nth 1 expr)))
  585. X           (math-mul (nth 1 expr)
  586. X                 (math-derivative (nth 2 expr)))))
  587. X    ((eq (car expr) '/)
  588. X     (math-sub (math-div (math-derivative (nth 1 expr))
  589. X                 (nth 2 expr))
  590. X           (math-div (math-mul (nth 1 expr)
  591. X                       (math-derivative (nth 2 expr)))
  592. X                 (math-sqr (nth 2 expr)))))
  593. X    ((eq (car expr) '^)
  594. X     (let ((du (math-derivative (nth 1 expr)))
  595. X           (dv (math-derivative (nth 2 expr))))
  596. X       (or (Math-zerop du)
  597. X           (setq du (math-mul (nth 2 expr)
  598. X                  (math-mul (math-normalize
  599. X                         (list '^
  600. X                           (nth 1 expr)
  601. X                           (math-add (nth 2 expr) -1)))
  602. X                        du))))
  603. X       (or (Math-zerop dv)
  604. X           (setq dv (math-mul (math-normalize
  605. X                   (list 'calcFunc-ln (nth 1 expr)))
  606. X                  (math-mul expr dv))))
  607. X       (math-add du dv)))
  608. X    ((eq (car expr) '%)
  609. X     (math-derivative (nth 1 expr)))   ; a reasonable definition
  610. X    ((eq (car expr) 'vec)
  611. X     (math-map-vec 'math-derivative expr))
  612. X    ((and (memq (car expr) '(calcFunc-conj calcFunc-re calcFunc-im))
  613. X          (= (length expr) 2))
  614. X     (list (car expr) (math-derivative (nth 1 expr))))
  615. X    ((and (memq (car expr) '(calcFunc-subscr calcFunc-mrow calcFunc-mcol))
  616. X          (= (length expr) 3))
  617. X     (let ((d (math-derivative (nth 1 expr))))
  618. X       (if (math-numberp d)
  619. X           0    ; assume x and x_1 are independent vars
  620. X         (list (car expr) d (nth 2 expr)))))
  621. X    (t (or (and (symbolp (car expr))
  622. X            (if (= (length expr) 2)
  623. X            (let ((handler (get (car expr) 'math-derivative)))
  624. X              (and handler
  625. X                   (let ((deriv (math-derivative (nth 1 expr))))
  626. X                 (if (Math-zerop deriv)
  627. X                     deriv
  628. X                   (math-mul (funcall handler (nth 1 expr))
  629. X                         deriv)))))
  630. X              (let ((handler (get (car expr) 'math-derivative-n)))
  631. X            (and handler
  632. X                 (funcall handler expr)))))
  633. X           (and (not (eq deriv-symb 'pre-expand))
  634. X            (let ((exp (math-expand-formula expr)))
  635. X              (and exp
  636. X               (or (let ((deriv-symb 'pre-expand))
  637. X                 (catch 'math-deriv (math-derivative expr)))
  638. X                   (math-derivative exp)))))
  639. X           (if (or (Math-objvecp expr)
  640. X               (eq (car expr) 'var)
  641. X               (not (symbolp (car expr))))
  642. X           (if deriv-symb
  643. X               (throw 'math-deriv nil)
  644. X             (list (if deriv-total 'calcFunc-tderiv 'calcFunc-deriv)
  645. X               expr
  646. X               deriv-var))
  647. X         (let ((accum 0)
  648. X               (arg expr)
  649. X               (n 1)
  650. X               derv)
  651. X           (while (setq arg (cdr arg))
  652. X             (or (Math-zerop (setq derv (math-derivative (car arg))))
  653. X             (let ((func (intern (concat (symbol-name (car expr))
  654. X                             "'"
  655. X                             (if (> n 1)
  656. X                             (int-to-string n)
  657. X                               ""))))
  658. X                   (prop (cond ((= (length expr) 2)
  659. X                        'math-derivative-1)
  660. X                       ((= (length expr) 3)
  661. X                        'math-derivative-2)
  662. X                       ((= (length expr) 4)
  663. X                        'math-derivative-3)
  664. X                       ((= (length expr) 5)
  665. X                        'math-derivative-4)
  666. X                       ((= (length expr) 6)
  667. X                        'math-derivative-5))))
  668. X               (setq accum
  669. X                 (math-add
  670. X                  accum
  671. X                  (math-mul
  672. X                   derv
  673. X                   (let ((handler (get func prop)))
  674. X                     (or (and prop handler
  675. X                          (apply handler (cdr expr)))
  676. X                     (if (and deriv-symb
  677. X                          (not (get func
  678. X                                'calc-user-defn)))
  679. X                         (throw 'math-deriv nil)
  680. X                       (cons func (cdr expr))))))))))
  681. X             (setq n (1+ n)))
  682. X           accum)))))
  683. )
  684. X
  685. (defun calcFunc-deriv (expr deriv-var &optional deriv-value deriv-symb)
  686. X  (let* ((deriv-total nil)
  687. X     (res (catch 'math-deriv (math-derivative expr))))
  688. X    (or (eq (car-safe res) 'calcFunc-deriv)
  689. X    (null res)
  690. X    (setq res (math-normalize res)))
  691. X    (and res
  692. X     (if deriv-value
  693. X         (math-expr-subst res deriv-var deriv-value)
  694. X       res)))
  695. )
  696. X
  697. (defun calcFunc-tderiv (expr deriv-var &optional deriv-value deriv-symb)
  698. X  (math-setup-declarations)
  699. X  (let* ((deriv-total t)
  700. X     (res (catch 'math-deriv (math-derivative expr))))
  701. X    (or (eq (car-safe res) 'calcFunc-tderiv)
  702. X    (null res)
  703. X    (setq res (math-normalize res)))
  704. X    (and res
  705. X     (if deriv-value
  706. X         (math-expr-subst res deriv-var deriv-value)
  707. X       res)))
  708. )
  709. X
  710. (put 'calcFunc-inv\' 'math-derivative-1
  711. X     (function (lambda (u) (math-neg (math-div 1 (math-sqr u))))))
  712. X
  713. (put 'calcFunc-sqrt\' 'math-derivative-1
  714. X     (function (lambda (u) (math-div 1 (math-mul 2 (list 'calcFunc-sqrt u))))))
  715. X
  716. (put 'calcFunc-deg\' 'math-derivative-1
  717. X     (function (lambda (u) (math-div-float '(float 18 1) (math-pi)))))
  718. X
  719. (put 'calcFunc-rad\' 'math-derivative-1
  720. X     (function (lambda (u) (math-pi-over-180))))
  721. X
  722. (put 'calcFunc-ln\' 'math-derivative-1
  723. X     (function (lambda (u) (math-div 1 u))))
  724. X
  725. (put 'calcFunc-log10\' 'math-derivative-1
  726. X     (function (lambda (u)
  727. X         (math-div (math-div 1 (math-normalize '(calcFunc-ln 10)))
  728. X               u))))
  729. X
  730. (put 'calcFunc-lnp1\' 'math-derivative-1
  731. X     (function (lambda (u) (math-div 1 (math-add u 1)))))
  732. X
  733. (put 'calcFunc-log\' 'math-derivative-2
  734. X     (function (lambda (x b)
  735. X         (and (not (Math-zerop b))
  736. X              (let ((lnv (math-normalize
  737. X                  (list 'calcFunc-ln b))))
  738. X            (math-div 1 (math-mul lnv x)))))))
  739. X
  740. (put 'calcFunc-log\'2 'math-derivative-2
  741. X     (function (lambda (x b)
  742. X         (let ((lnv (list 'calcFunc-ln b)))
  743. X           (math-neg (math-div (list 'calcFunc-log x b)
  744. X                       (math-mul lnv b)))))))
  745. X
  746. (put 'calcFunc-exp\' 'math-derivative-1
  747. X     (function (lambda (u) (math-normalize (list 'calcFunc-exp u)))))
  748. X
  749. (put 'calcFunc-expm1\' 'math-derivative-1
  750. X     (function (lambda (u) (math-normalize (list 'calcFunc-expm1 u)))))
  751. X
  752. (put 'calcFunc-sin\' 'math-derivative-1
  753. X     (function (lambda (u) (math-to-radians-2 (math-normalize
  754. X                           (list 'calcFunc-cos u))))))
  755. X
  756. (put 'calcFunc-cos\' 'math-derivative-1
  757. X     (function (lambda (u) (math-neg (math-to-radians-2
  758. X                      (math-normalize
  759. X                       (list 'calcFunc-sin u)))))))
  760. X
  761. (put 'calcFunc-tan\' 'math-derivative-1
  762. X     (function (lambda (u) (math-to-radians-2
  763. X                (math-div 1 (math-sqr
  764. X                     (math-normalize
  765. X                      (list 'calcFunc-cos u))))))))
  766. X
  767. (put 'calcFunc-arcsin\' 'math-derivative-1
  768. X     (function (lambda (u)
  769. X         (math-from-radians-2
  770. X          (math-div 1 (math-normalize
  771. X                   (list 'calcFunc-sqrt
  772. X                     (math-sub 1 (math-sqr u)))))))))
  773. X
  774. (put 'calcFunc-arccos\' 'math-derivative-1
  775. X     (function (lambda (u)
  776. X         (math-from-radians-2
  777. X          (math-div -1 (math-normalize
  778. X                (list 'calcFunc-sqrt
  779. X                      (math-sub 1 (math-sqr u)))))))))
  780. X
  781. (put 'calcFunc-arctan\' 'math-derivative-1
  782. X     (function (lambda (u) (math-from-radians-2
  783. X                (math-div 1 (math-add 1 (math-sqr u)))))))
  784. X
  785. (put 'calcFunc-sinh\' 'math-derivative-1
  786. X     (function (lambda (u) (math-normalize (list 'calcFunc-cosh u)))))
  787. X
  788. (put 'calcFunc-cosh\' 'math-derivative-1
  789. X     (function (lambda (u) (math-normalize (list 'calcFunc-sinh u)))))
  790. X
  791. (put 'calcFunc-tanh\' 'math-derivative-1
  792. X     (function (lambda (u) (math-div 1 (math-sqr
  793. X                    (math-normalize
  794. X                     (list 'calcFunc-cosh u)))))))
  795. X
  796. (put 'calcFunc-arcsinh\' 'math-derivative-1
  797. X     (function (lambda (u)
  798. X         (math-div 1 (math-normalize
  799. X                  (list 'calcFunc-sqrt
  800. X                    (math-add (math-sqr u) 1)))))))
  801. X
  802. (put 'calcFunc-arccosh\' 'math-derivative-1
  803. X     (function (lambda (u)
  804. X          (math-div 1 (math-normalize
  805. X                   (list 'calcFunc-sqrt
  806. X                     (math-add (math-sqr u) -1)))))))
  807. X
  808. (put 'calcFunc-arctanh\' 'math-derivative-1
  809. X     (function (lambda (u) (math-div 1 (math-sub 1 (math-sqr u))))))
  810. X
  811. (put 'calcFunc-bern\'2 'math-derivative-2
  812. X     (function (lambda (n x)
  813. X         (math-mul n (list 'calcFunc-bern (math-add n -1) x)))))
  814. X
  815. (put 'calcFunc-euler\'2 'math-derivative-2
  816. X     (function (lambda (n x)
  817. X         (math-mul n (list 'calcFunc-euler (math-add n -1) x)))))
  818. X
  819. (put 'calcFunc-gammag\'2 'math-derivative-2
  820. X     (function (lambda (a x) (math-deriv-gamma a x 1))))
  821. X
  822. (put 'calcFunc-gammaG\'2 'math-derivative-2
  823. X     (function (lambda (a x) (math-deriv-gamma a x -1))))
  824. X
  825. (put 'calcFunc-gammaP\'2 'math-derivative-2
  826. X     (function (lambda (a x) (math-deriv-gamma a x
  827. X                           (math-div
  828. X                        1 (math-normalize
  829. X                           (list 'calcFunc-gamma
  830. X                             a)))))))
  831. X
  832. (put 'calcFunc-gammaQ\'2 'math-derivative-2
  833. X     (function (lambda (a x) (math-deriv-gamma a x
  834. X                           (math-div
  835. X                        -1 (math-normalize
  836. X                            (list 'calcFunc-gamma
  837. X                              a)))))))
  838. X
  839. (defun math-deriv-gamma (a x scale)
  840. X  (math-mul scale
  841. X        (math-mul (math-pow x (math-add a -1))
  842. X              (list 'calcFunc-exp (math-neg x))))
  843. )
  844. X
  845. (put 'calcFunc-betaB\' 'math-derivative-3
  846. X     (function (lambda (x a b) (math-deriv-beta x a b 1))))
  847. X
  848. (put 'calcFunc-betaI\' 'math-derivative-3
  849. X     (function (lambda (x a b) (math-deriv-beta x a b
  850. X                        (math-div
  851. X                         1 (list 'calcFunc-beta
  852. X                             a b))))))
  853. X
  854. (defun math-deriv-beta (x a b scale)
  855. X  (math-mul (math-mul (math-pow x (math-add a -1))
  856. X              (math-pow (math-sub 1 x) (math-add b -1)))
  857. X        scale)
  858. )
  859. X
  860. (put 'calcFunc-erf\' 'math-derivative-1
  861. X     (function (lambda (x) (math-div 2
  862. X                     (math-mul (list 'calcFunc-exp
  863. X                             (math-sqr x))
  864. X                           (if calc-symbolic-mode
  865. X                           '(calcFunc-sqrt
  866. X                             (var pi var-pi))
  867. X                         (math-sqrt-pi)))))))
  868. X
  869. (put 'calcFunc-erfc\' 'math-derivative-1
  870. X     (function (lambda (x) (math-div -2
  871. X                     (math-mul (list 'calcFunc-exp
  872. X                             (math-sqr x))
  873. X                           (if calc-symbolic-mode
  874. X                           '(calcFunc-sqrt
  875. X                             (var pi var-pi))
  876. X                         (math-sqrt-pi)))))))
  877. X
  878. (put 'calcFunc-besJ\'2 'math-derivative-2
  879. X     (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besJ
  880. X                               (math-add v -1)
  881. X                               z)
  882. X                         (list 'calcFunc-besJ
  883. X                               (math-add v 1)
  884. X                               z))
  885. X                       2))))
  886. X
  887. (put 'calcFunc-besY\'2 'math-derivative-2
  888. X     (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besY
  889. X                               (math-add v -1)
  890. X                               z)
  891. X                         (list 'calcFunc-besY
  892. X                               (math-add v 1)
  893. X                               z))
  894. X                       2))))
  895. X
  896. (put 'calcFunc-sum 'math-derivative-n
  897. X     (function
  898. X      (lambda (expr)
  899. X    (if (math-expr-contains (cons 'vec (cdr (cdr expr))) deriv-var)
  900. X        (throw 'math-deriv nil)
  901. X      (cons 'calcFunc-sum
  902. X        (cons (math-derivative (nth 1 expr))
  903. X              (cdr (cdr expr))))))))
  904. X
  905. (put 'calcFunc-prod 'math-derivative-n
  906. X     (function
  907. X      (lambda (expr)
  908. X    (if (math-expr-contains (cons 'vec (cdr (cdr expr))) deriv-var)
  909. X        (throw 'math-deriv nil)
  910. X      (math-mul expr
  911. X            (cons 'calcFunc-sum
  912. X              (cons (math-div (math-derivative (nth 1 expr))
  913. X                      (nth 1 expr))
  914. X                (cdr (cdr expr)))))))))
  915. X
  916. (put 'calcFunc-integ 'math-derivative-n
  917. X     (function
  918. X      (lambda (expr)
  919. X    (if (= (length expr) 3)
  920. X        (if (equal (nth 2 expr) deriv-var)
  921. X        (nth 1 expr)
  922. X          (math-normalize
  923. X           (list 'calcFunc-integ
  924. X             (math-derivative (nth 1 expr))
  925. X             (nth 2 expr))))
  926. X      (if (= (length expr) 5)
  927. X          (let ((lower (math-expr-subst (nth 1 expr) (nth 2 expr)
  928. X                        (nth 3 expr)))
  929. X            (upper (math-expr-subst (nth 1 expr) (nth 2 expr)
  930. X                        (nth 4 expr))))
  931. X        (math-add (math-sub (math-mul upper
  932. X                          (math-derivative (nth 4 expr)))
  933. X                    (math-mul lower
  934. X                          (math-derivative (nth 3 expr))))
  935. X              (if (equal (nth 2 expr) deriv-var)
  936. X                  0
  937. X                (math-normalize
  938. X                 (list 'calcFunc-integ
  939. X                   (math-derivative (nth 1 expr)) (nth 2 expr)
  940. X                   (nth 3 expr) (nth 4 expr)))))))))))
  941. X
  942. (put 'calcFunc-if 'math-derivative-n
  943. X     (function
  944. X      (lambda (expr)
  945. X    (and (= (length expr) 4)
  946. X         (list 'calcFunc-if (nth 1 expr)
  947. X           (math-derivative (nth 2 expr))
  948. X           (math-derivative (nth 3 expr)))))))
  949. X
  950. (put 'calcFunc-subscr 'math-derivative-n
  951. X     (function
  952. X      (lambda (expr)
  953. X    (and (= (length expr) 3)
  954. X         (list 'calcFunc-subscr (nth 1 expr)
  955. X           (math-derivative (nth 2 expr)))))))
  956. X
  957. X
  958. X
  959. X
  960. X
  961. (setq math-integ-var '(var X ---))
  962. (setq math-integ-var-2 '(var Y ---))
  963. (setq math-integ-vars (list 'f math-integ-var math-integ-var-2))
  964. (setq math-integ-var-list (list math-integ-var))
  965. (setq math-integ-var-list-list (list math-integ-var-list))
  966. X
  967. (defmacro math-tracing-integral (&rest parts)
  968. X  (list 'and
  969. X    'trace-buffer
  970. X    (list 'save-excursion
  971. X          '(set-buffer trace-buffer)
  972. X          '(goto-char (point-max))
  973. X          (list 'and
  974. X            '(bolp)
  975. X            '(insert (make-string (- math-integral-limit
  976. X                         math-integ-level) 32)
  977. X                 (format "%2d " math-integ-depth)
  978. X                 (make-string math-integ-level 32)))
  979. X          (cons 'insert parts)
  980. X          '(sit-for 0)))
  981. )
  982. X
  983. ;;; The following wrapper caches results and avoids infinite recursion.
  984. ;;; Each cache entry is: ( A B )          Integral of A is B;
  985. ;;;             ( A N )          Integral of A failed at level N;
  986. ;;;             ( A busy )      Currently working on integral of A;
  987. ;;;             ( A parts )      Currently working, integ-by-parts;
  988. ;;;             ( A parts2 )      Currently working, integ-by-parts;
  989. ;;;             ( A cancelled )  Ignore this cache entry;
  990. ;;;             ( A [B] )        Same result as for cur-record = B.
  991. (defun math-integral (expr &optional simplify same-as-above)
  992. X  (let* ((simp cur-record)
  993. X     (cur-record (assoc expr math-integral-cache))
  994. X     (math-integ-depth (1+ math-integ-depth))
  995. X     (val 'cancelled))
  996. X    (math-tracing-integral "Integrating "
  997. X               (math-format-value expr 1000)
  998. X               "...\n")
  999. X    (and cur-record
  1000. X     (progn
  1001. X       (math-tracing-integral "Found "
  1002. X                  (math-format-value (nth 1 cur-record) 1000))
  1003. X       (and (consp (nth 1 cur-record))
  1004. X        (math-replace-integral-parts cur-record))
  1005. X       (math-tracing-integral " => "
  1006. X                  (math-format-value (nth 1 cur-record) 1000)
  1007. X                  "\n")))
  1008. X    (or (and cur-record
  1009. X         (not (eq (nth 1 cur-record) 'cancelled))
  1010. X         (or (not (integerp (nth 1 cur-record)))
  1011. X         (>= (nth 1 cur-record) math-integ-level)))
  1012. X    (and (math-integral-contains-parts expr)
  1013. X         (progn
  1014. X           (setq val nil)
  1015. X           t))
  1016. X    (unwind-protect
  1017. X        (progn
  1018. X          (let (math-integ-msg)
  1019. X        (if (eq calc-display-working-message 'lots)
  1020. X            (progn
  1021. X              (calc-set-command-flag 'clear-message)
  1022. X              (setq math-integ-msg (format
  1023. X                        "Working... Integrating %s"
  1024. X                        (math-format-flat-expr expr 0)))
  1025. X              (message math-integ-msg)))
  1026. X        (if cur-record
  1027. X            (setcar (cdr cur-record)
  1028. X                (if same-as-above (vector simp) 'busy))
  1029. X          (setq cur-record
  1030. X            (list expr (if same-as-above (vector simp) 'busy))
  1031. X            math-integral-cache (cons cur-record
  1032. X                          math-integral-cache)))
  1033. X        (if (eq simplify 'yes)
  1034. X            (progn
  1035. X              (math-tracing-integral "Simplifying...")
  1036. X              (setq simp (math-simplify expr))
  1037. X              (setq val (if (equal simp expr)
  1038. X                    (progn
  1039. X                      (math-tracing-integral " no change\n")
  1040. X                      (math-do-integral expr))
  1041. X                  (math-tracing-integral " simplified\n")
  1042. X                  (math-integral simp 'no t))))
  1043. X          (or (setq val (math-do-integral expr))
  1044. X              (eq simplify 'no)
  1045. X              (let ((simp (math-simplify expr)))
  1046. X            (or (equal simp expr)
  1047. X                (progn
  1048. X                  (math-tracing-integral "Trying again after "
  1049. X                             "simplification...\n")
  1050. X                  (setq val (math-integral simp 'no t))))))))
  1051. X          (if (eq calc-display-working-message 'lots)
  1052. X          (message math-integ-msg)))
  1053. X      (setcar (cdr cur-record) (or val
  1054. X                       (if (or math-enable-subst
  1055. X                           (not math-any-substs))
  1056. X                       math-integ-level
  1057. X                     'cancelled)))))
  1058. X    (setq val cur-record)
  1059. X    (while (vectorp (nth 1 val))
  1060. X      (setq val (aref (nth 1 val) 0)))
  1061. X    (setq val (if (memq (nth 1 val) '(parts parts2))
  1062. X          (progn
  1063. X            (setcar (cdr val) 'parts2)
  1064. X            (list 'var 'PARTS val))
  1065. X        (and (consp (nth 1 val))
  1066. X             (nth 1 val))))
  1067. X    (math-tracing-integral "Integral of "
  1068. X               (math-format-value expr 1000)
  1069. X               "  is  "
  1070. X               (math-format-value val 1000)
  1071. X               "\n")
  1072. X    val)
  1073. )
  1074. (defvar math-integral-cache nil)
  1075. (defvar math-integral-cache-state nil)
  1076. X
  1077. (defun math-integral-contains-parts (expr)
  1078. X  (if (Math-primp expr)
  1079. X      (and (eq (car-safe expr) 'var)
  1080. X       (eq (nth 1 expr) 'PARTS)
  1081. X       (listp (nth 2 expr)))
  1082. X    (while (and (setq expr (cdr expr))
  1083. X        (not (math-integral-contains-parts (car expr)))))
  1084. X    expr)
  1085. )
  1086. X
  1087. (defun math-replace-integral-parts (expr)
  1088. X  (or (Math-primp expr)
  1089. X      (while (setq expr (cdr expr))
  1090. X    (and (consp (car expr))
  1091. X         (if (eq (car (car expr)) 'var)
  1092. X         (and (eq (nth 1 (car expr)) 'PARTS)
  1093. X              (consp (nth 2 (car expr)))
  1094. X              (if (listp (nth 1 (nth 2 (car expr))))
  1095. X              (progn
  1096. X                (setcar expr (nth 1 (nth 2 (car expr))))
  1097. X                (math-replace-integral-parts (cons 'foo expr)))
  1098. X            (setcar (cdr cur-record) 'cancelled)))
  1099. X           (math-replace-integral-parts (car expr))))))
  1100. )
  1101. X
  1102. (defun math-do-integral (expr)
  1103. X  (let (t1 t2)
  1104. X    (or (cond ((not (math-expr-contains expr math-integ-var))
  1105. X           (math-mul expr math-integ-var))
  1106. X          ((equal expr math-integ-var)
  1107. X           (math-div (math-sqr expr) 2))
  1108. X          ((eq (car expr) '+)
  1109. X           (and (setq t1 (math-integral (nth 1 expr)))
  1110. X            (setq t2 (math-integral (nth 2 expr)))
  1111. X            (math-add t1 t2)))
  1112. X          ((eq (car expr) '-)
  1113. X           (and (setq t1 (math-integral (nth 1 expr)))
  1114. X            (setq t2 (math-integral (nth 2 expr)))
  1115. X            (math-sub t1 t2)))
  1116. X          ((eq (car expr) 'neg)
  1117. X           (and (setq t1 (math-integral (nth 1 expr)))
  1118. X            (math-neg t1)))
  1119. X          ((eq (car expr) '*)
  1120. X           (cond ((not (math-expr-contains (nth 1 expr) math-integ-var))
  1121. X              (and (setq t1 (math-integral (nth 2 expr)))
  1122. X               (math-mul (nth 1 expr) t1)))
  1123. X             ((not (math-expr-contains (nth 2 expr) math-integ-var))
  1124. X              (and (setq t1 (math-integral (nth 1 expr)))
  1125. X               (math-mul t1 (nth 2 expr))))
  1126. X             ((memq (car-safe (nth 1 expr)) '(+ -))
  1127. X              (math-integral (list (car (nth 1 expr))
  1128. X                       (math-mul (nth 1 (nth 1 expr))
  1129. X                             (nth 2 expr))
  1130. X                       (math-mul (nth 2 (nth 1 expr))
  1131. X                             (nth 2 expr)))
  1132. X                     'yes t))
  1133. X             ((memq (car-safe (nth 2 expr)) '(+ -))
  1134. X              (math-integral (list (car (nth 2 expr))
  1135. X                       (math-mul (nth 1 (nth 2 expr))
  1136. X                             (nth 1 expr))
  1137. X                       (math-mul (nth 2 (nth 2 expr))
  1138. X                             (nth 1 expr)))
  1139. X                     'yes t))))
  1140. X          ((eq (car expr) '/)
  1141. X           (cond ((and (not (math-expr-contains (nth 1 expr)
  1142. X                            math-integ-var))
  1143. X               (not (math-equal-int (nth 1 expr) 1)))
  1144. X              (and (setq t1 (math-integral (math-div 1 (nth 2 expr))))
  1145. X               (math-mul (nth 1 expr) t1)))
  1146. X             ((not (math-expr-contains (nth 2 expr) math-integ-var))
  1147. X              (and (setq t1 (math-integral (nth 1 expr)))
  1148. X               (math-div t1 (nth 2 expr))))
  1149. X             ((and (eq (car-safe (nth 1 expr)) '*)
  1150. X               (not (math-expr-contains (nth 1 (nth 1 expr))
  1151. X                            math-integ-var)))
  1152. X              (and (setq t1 (math-integral
  1153. X                     (math-div (nth 2 (nth 1 expr))
  1154. X                           (nth 2 expr))))
  1155. X               (math-mul t1 (nth 1 (nth 1 expr)))))
  1156. X             ((and (eq (car-safe (nth 2 expr)) '*)
  1157. X               (not (math-expr-contains (nth 1 (nth 2 expr))
  1158. X                            math-integ-var)))
  1159. X              (and (setq t1 (math-integral
  1160. X                     (math-div (nth 1 expr)
  1161. X                           (nth 2 (nth 2 expr)))))
  1162. X               (math-div t1 (nth 1 (nth 2 expr)))))))
  1163. X          ((eq (car expr) '^)
  1164. X           (cond ((not (math-expr-contains (nth 1 expr) math-integ-var))
  1165. X              (or (and (setq t1 (math-is-polynomial (nth 2 expr)
  1166. X                                math-integ-var 1))
  1167. X                   (math-div expr
  1168. X                     (math-mul (nth 1 t1)
  1169. X                           (math-normalize
  1170. X                            (list 'calcFunc-ln
  1171. X                              (nth 1 expr))))))
  1172. X              (math-integral
  1173. X               (list 'calcFunc-exp
  1174. X                 (math-mul (nth 2 expr)
  1175. X                       (math-normalize
  1176. X                        (list 'calcFunc-ln
  1177. X                          (nth 1 expr)))))
  1178. X               'yes t)))
  1179. X             ((not (math-expr-contains (nth 2 expr) math-integ-var))
  1180. X              (if (and (integerp (nth 2 expr)) (< (nth 2 expr) 0))
  1181. X              (math-integral
  1182. X               (list '/ 1 (math-pow (nth 1 expr) (- (nth 2 expr))))
  1183. X               nil t)
  1184. X            (or (and (setq t1 (math-is-polynomial (nth 1 expr)
  1185. X                                  math-integ-var
  1186. X                                  1))
  1187. X                 (setq t2 (math-add (nth 2 expr) 1))
  1188. X                 (math-div (math-pow (nth 1 expr) t2)
  1189. X                       (math-mul t2 (nth 1 t1))))
  1190. X                (and (Math-negp (nth 2 expr))
  1191. X                 (math-integral
  1192. X                  (math-div 1
  1193. X                        (math-pow (nth 1 expr)
  1194. X                              (math-neg
  1195. X                               (nth 2 expr))))
  1196. X                  nil t))
  1197. X                nil))))))
  1198. X
  1199. X    ;; Integral of a polynomial.
  1200. X    (and (setq t1 (math-is-polynomial expr math-integ-var 20))
  1201. X         (let ((accum 0)
  1202. X           (n 1))
  1203. X           (while t1
  1204. X         (if (setq accum (math-add accum
  1205. X                       (math-div (math-mul (car t1)
  1206. X                                   (math-pow
  1207. X                                math-integ-var
  1208. X                                n))
  1209. X                             n))
  1210. X               t1 (cdr t1))
  1211. X             (setq n (1+ n))))
  1212. X           accum))
  1213. X
  1214. X    ;; Try looking it up!
  1215. X    (cond ((= (length expr) 2)
  1216. X           (and (symbolp (car expr))
  1217. X            (setq t1 (get (car expr) 'math-integral))
  1218. X            (progn
  1219. X              (while (and t1
  1220. X                  (not (setq t2 (funcall (car t1)
  1221. X                             (nth 1 expr)))))
  1222. X            (setq t1 (cdr t1)))
  1223. X              (and t2 (math-normalize t2)))))
  1224. X          ((= (length expr) 3)
  1225. X           (and (symbolp (car expr))
  1226. X            (setq t1 (get (car expr) 'math-integral-2))
  1227. X            (progn
  1228. X              (while (and t1
  1229. X                  (not (setq t2 (funcall (car t1)
  1230. X                             (nth 1 expr)
  1231. X                             (nth 2 expr)))))
  1232. X            (setq t1 (cdr t1)))
  1233. X              (and t2 (math-normalize t2))))))
  1234. X
  1235. X    ;; Integral of a rational function.
  1236. X    (and (math-ratpoly-p expr math-integ-var)
  1237. X         (setq t1 (calcFunc-apart expr math-integ-var))
  1238. X         (not (equal t1 expr))
  1239. X         (math-integral t1))
  1240. X
  1241. X    ;; Try user-defined integration rules.
  1242. X    (and (calc-has-rules 'var-IntegRules)
  1243. X         (let ((math-old-integ (symbol-function 'calcFunc-integ))
  1244. X           (input (list 'calcFunc-integtry expr math-integ-var))
  1245. X           res part)
  1246. X           (unwind-protect
  1247. X           (progn
  1248. X             (fset 'calcFunc-integ 'math-sub-integration)
  1249. X             (setq res (math-rewrite input
  1250. X                         '(var IntegRules var-IntegRules)
  1251. X                         1))
  1252. X             (fset 'calcFunc-integ math-old-integ)
  1253. X             (and (not (equal res input))
  1254. X              (if (setq part (math-expr-calls
  1255. X                      res '(calcFunc-integsubst)))
  1256. X                  (and (memq (length part) '(3 4 5))
  1257. X                   (let ((parts (mapcar
  1258. X                         (function
  1259. X                          (lambda (x)
  1260. X                            (math-expr-subst
  1261. X                             x (nth 2 part)
  1262. X                             math-integ-var)))
  1263. X                         (cdr part))))
  1264. X                     (math-integrate-by-substitution
  1265. X                      expr (car parts) t
  1266. X                      (or (nth 2 parts)
  1267. X                      (list 'calcFunc-integfailed
  1268. X                        math-integ-var))
  1269. X                      (nth 3 parts))))
  1270. X                (if (not (math-expr-calls res
  1271. X                              '(calcFunc-integtry
  1272. X                            calcFunc-integfailed)))
  1273. X                res))))
  1274. X         (fset 'calcFunc-integ math-old-integ))))
  1275. X
  1276. X    ;; See if the function is a symbolic derivative.
  1277. X    (and (string-match "'" (symbol-name (car expr)))
  1278. X         (let ((name (symbol-name (car expr)))
  1279. X           (p expr) (n 0) (which nil) (bad nil))
  1280. X           (while (setq n (1+ n) p (cdr p))
  1281. X         (if (equal (car p) math-integ-var)
  1282. X             (if which (setq bad t) (setq which n))
  1283. X           (if (math-expr-contains (car p) math-integ-var)
  1284. X               (setq bad t))))
  1285. X           (and which (not bad)
  1286. X            (let ((prime (if (= which 1) "'" (format "'%d" which))))
  1287. X              (and (string-match (concat prime "\\('['0-9]*\\|$\\)")
  1288. X                     name)
  1289. X               (cons (intern
  1290. X                  (concat
  1291. X                   (substring name 0 (match-beginning 0))
  1292. X                   (substring name (+ (match-beginning 0)
  1293. X                              (length prime)))))
  1294. X                 (cdr expr)))))))
  1295. X
  1296. X    ;; Try transformation methods (parts, substitutions).
  1297. X    (and (> math-integ-level 0)
  1298. X         (math-do-integral-methods expr))
  1299. X
  1300. X    ;; Try expanding the function's definition.
  1301. X    (let ((res (math-expand-formula expr)))
  1302. X      (and res
  1303. X           (math-integral res)))))
  1304. )
  1305. X
  1306. (defun math-sub-integration (expr &rest rest)
  1307. X  (or (if (or (not rest)
  1308. X          (and (< math-integ-level math-integral-limit)
  1309. X           (eq (car rest) math-integ-var)))
  1310. X      (math-integral expr)
  1311. X    (let ((res (apply math-old-integ expr rest)))
  1312. X      (and (or (= math-integ-level math-integral-limit)
  1313. X           (not (math-expr-calls res 'calcFunc-integ)))
  1314. X           res)))
  1315. X      (list 'calcFunc-integfailed expr))
  1316. )
  1317. X
  1318. (defun math-do-integral-methods (expr)
  1319. X  (let ((so-far math-integ-var-list-list)
  1320. X    rat-in)
  1321. X
  1322. X    ;; Integration by substitution, for various likely sub-expressions.
  1323. X    ;; (In first pass, we look only for sub-exprs that are linear in X.)
  1324. X    (or (if math-enable-subst
  1325. X        (math-integ-try-substitutions expr)
  1326. X      (math-integ-try-linear-substitutions expr))
  1327. X
  1328. X    ;; If function has sines and cosines, try tan(x/2) substitution.
  1329. X    (and (let ((p (setq rat-in (math-expr-rational-in expr))))
  1330. X           (while (and p
  1331. X               (memq (car (car p)) '(calcFunc-sin
  1332. X                         calcFunc-cos
  1333. X                         calcFunc-tan))
  1334. X               (equal (nth 1 (car p)) math-integ-var))
  1335. X         (setq p (cdr p)))
  1336. X           (null p))
  1337. X         (or (and (math-integ-parts-easy expr)
  1338. X              (math-integ-try-parts expr t))
  1339. X         (math-integrate-by-good-substitution
  1340. X          expr (list 'calcFunc-tan (math-div math-integ-var 2)))))
  1341. X
  1342. X    ;; If function has sinh and cosh, try tanh(x/2) substitution.
  1343. X    (and (let ((p rat-in))
  1344. X           (while (and p
  1345. X               (memq (car (car p)) '(calcFunc-sinh
  1346. X                         calcFunc-cosh
  1347. X                         calcFunc-tanh
  1348. X                         calcFunc-exp))
  1349. X               (equal (nth 1 (car p)) math-integ-var))
  1350. X         (setq p (cdr p)))
  1351. X           (null p))
  1352. X         (or (and (math-integ-parts-easy expr)
  1353. X              (math-integ-try-parts expr t))
  1354. X         (math-integrate-by-good-substitution
  1355. X          expr (list 'calcFunc-tanh (math-div math-integ-var 2)))))
  1356. X
  1357. X    ;; If function has square roots, try sin, tan, or sec substitution.
  1358. X    (and (let ((p rat-in))
  1359. X           (setq t1 nil)
  1360. X           (while (and p
  1361. X               (or (equal (car p) math-integ-var)
  1362. X                   (and (eq (car (car p)) 'calcFunc-sqrt)
  1363. X                    (setq t1 (math-is-polynomial
  1364. X                          (nth 1 (setq t2 (car p)))
  1365. X                          math-integ-var 2)))))
  1366. X         (setq p (cdr p)))
  1367. X           (and (null p) t1))
  1368. X         (if (cdr (cdr t1))
  1369. X         (if (math-guess-if-neg (nth 2 t1))
  1370. X             (let* ((c (math-sqrt (math-neg (nth 2 t1))))
  1371. X                (d (math-div (nth 1 t1) (math-mul -2 c)))
  1372. X                (a (math-sqrt (math-add (car t1) (math-sqr d)))))
  1373. X               (math-integrate-by-good-substitution
  1374. X            expr (list 'calcFunc-arcsin
  1375. X                   (math-div-thru
  1376. X                    (math-add (math-mul c math-integ-var) d)
  1377. X                    a))))
  1378. X           (let* ((c (math-sqrt (nth 2 t1)))
  1379. X              (d (math-div (nth 1 t1) (math-mul 2 c)))
  1380. X              (aa (math-sub (car t1) (math-sqr d))))
  1381. X             (if (and nil (not (and (eq d 0) (eq c 1))))
  1382. X             (math-integrate-by-good-substitution
  1383. X              expr (math-add (math-mul c math-integ-var) d))
  1384. X               (if (math-guess-if-neg aa)
  1385. X               (math-integrate-by-good-substitution
  1386. X                expr (list 'calcFunc-arccosh
  1387. X                       (math-div-thru
  1388. X                    (math-add (math-mul c math-integ-var)
  1389. X                          d)
  1390. X                    (math-sqrt (math-neg aa)))))
  1391. X             (math-integrate-by-good-substitution
  1392. X              expr (list 'calcFunc-arcsinh
  1393. X                     (math-div-thru
  1394. X                      (math-add (math-mul c math-integ-var)
  1395. X                        d)
  1396. X                      (math-sqrt aa))))))))
  1397. X           (math-integrate-by-good-substitution expr t2)) )
  1398. X
  1399. X    ;; Try integration by parts.
  1400. X    (math-integ-try-parts expr)
  1401. X
  1402. X    ;; Give up.
  1403. X    nil))
  1404. )
  1405. X
  1406. (defun math-integ-parts-easy (expr)
  1407. X  (cond ((Math-primp expr) t)
  1408. X    ((memq (car expr) '(+ - *))
  1409. X     (and (math-integ-parts-easy (nth 1 expr))
  1410. X          (math-integ-parts-easy (nth 2 expr))))
  1411. X    ((eq (car expr) '/)
  1412. X     (and (math-integ-parts-easy (nth 1 expr))
  1413. X          (math-atomic-factorp (nth 2 expr))))
  1414. X    ((eq (car expr) '^)
  1415. X     (and (natnump (nth 2 expr))
  1416. X          (math-integ-parts-easy (nth 1 expr))))
  1417. X    ((eq (car expr) 'neg)
  1418. X     (math-integ-parts-easy (nth 1 expr)))
  1419. X    (t t))
  1420. )
  1421. X
  1422. (defun math-integ-try-parts (expr &optional math-good-parts)
  1423. X  ;; Integration by parts:
  1424. X  ;;   integ(f(x) g(x),x) = f(x) h(x) - integ(h(x) f'(x),x)
  1425. X  ;;     where h(x) = integ(g(x),x).
  1426. X  (or (let ((exp (calcFunc-expand expr)))
  1427. X    (and (not (equal exp expr))
  1428. X         (math-integral exp)))
  1429. X      (and (eq (car expr) '*)
  1430. X       (let ((first-bad (or (math-polynomial-p (nth 1 expr)
  1431. X                           math-integ-var)
  1432. X                (equal (nth 2 expr) math-prev-parts-v))))
  1433. X         (or (and first-bad   ; so try this one first
  1434. X              (math-integrate-by-parts (nth 1 expr) (nth 2 expr)))
  1435. X         (math-integrate-by-parts (nth 2 expr) (nth 1 expr))
  1436. X         (and (not first-bad)
  1437. X              (math-integrate-by-parts (nth 1 expr) (nth 2 expr))))))
  1438. X      (and (eq (car expr) '/)
  1439. X       (math-expr-contains (nth 1 expr) math-integ-var)
  1440. X       (let ((recip (math-div 1 (nth 2 expr))))
  1441. X         (or (math-integrate-by-parts (nth 1 expr) recip)
  1442. X         (math-integrate-by-parts recip (nth 1 expr)))))
  1443. X      (and (eq (car expr) '^)
  1444. X       (math-integrate-by-parts (math-pow (nth 1 expr)
  1445. X                          (math-sub (nth 2 expr) 1))
  1446. X                    (nth 1 expr))))
  1447. )
  1448. X
  1449. (defun math-integrate-by-parts (u vprime)
  1450. X  (let ((math-integ-level (if (or math-good-parts
  1451. X                  (math-polynomial-p u math-integ-var))
  1452. X                  math-integ-level
  1453. X                (1- math-integ-level)))
  1454. X    (math-doing-parts t)
  1455. X    v temp)
  1456. X    (and (>= math-integ-level 0)
  1457. X     (unwind-protect
  1458. X         (progn
  1459. X           (setcar (cdr cur-record) 'parts)
  1460. X           (math-tracing-integral "Integrating by parts, u = "
  1461. X                      (math-format-value u 1000)
  1462. X                      ", v' = "
  1463. X                      (math-format-value vprime 1000)
  1464. X                      "\n")
  1465. X           (and (setq v (math-integral vprime))
  1466. X            (setq temp (calcFunc-deriv u math-integ-var nil t))
  1467. X            (setq temp (let ((math-prev-parts-v v))
  1468. X                 (math-integral (math-mul v temp) 'yes)))
  1469. X            (setq temp (math-sub (math-mul u v) temp))
  1470. X            (if (eq (nth 1 cur-record) 'parts)
  1471. X            (calcFunc-expand temp)
  1472. X              (setq v (list 'var 'PARTS cur-record)
  1473. X                var-thing (list 'vec (math-sub v temp) v)
  1474. X                temp (let (calc-next-why)
  1475. X                   (math-solve-for (math-sub v temp) 0 v nil)))
  1476. X              (and temp (not (integerp temp))
  1477. X               (math-simplify-extended temp)))))
  1478. X       (setcar (cdr cur-record) 'busy))))
  1479. )
  1480. X
  1481. ;;; This tries two different formulations, hoping the algebraic simplifier
  1482. ;;; will be strong enough to handle at least one.
  1483. (defun math-integrate-by-substitution (expr u &optional user uinv uinvprime)
  1484. X  (and (> math-integ-level 0)
  1485. X       (let ((math-integ-level (max (- math-integ-level 2) 0)))
  1486. X     (math-integrate-by-good-substitution expr u user uinv uinvprime)))
  1487. )
  1488. X
  1489. (defun math-integrate-by-good-substitution (expr u &optional user
  1490. X                         uinv uinvprime)
  1491. X  (let ((math-living-dangerously t)
  1492. X    deriv temp)
  1493. X    (and (setq uinv (if uinv
  1494. X            (math-expr-subst uinv math-integ-var
  1495. X                     math-integ-var-2)
  1496. X              (let (calc-next-why)
  1497. X            (math-solve-for u
  1498. X                    math-integ-var-2
  1499. X                    math-integ-var nil))))
  1500. X     (progn
  1501. X       (math-tracing-integral "Integrating by substitution, u = "
  1502. X                  (math-format-value u 1000)
  1503. X                  "\n")
  1504. X       (or (and (setq deriv (calcFunc-deriv u
  1505. X                        math-integ-var nil
  1506. X                        (not user)))
  1507. X            (setq temp (math-integral (math-expr-subst
  1508. X                           (math-expr-subst
  1509. X                        (math-expr-subst
  1510. X                         (math-div expr deriv)
  1511. X                         u
  1512. X                         math-integ-var-2)
  1513. X                        math-integ-var
  1514. X                        uinv)
  1515. X                           math-integ-var-2
  1516. X                           math-integ-var)
  1517. X                          'yes)))
  1518. X           (and (setq deriv (or uinvprime
  1519. X                    (calcFunc-deriv uinv
  1520. X                            math-integ-var-2
  1521. X                            math-integ-var
  1522. X                            (not user))))
  1523. X            (setq temp (math-integral (math-mul
  1524. X                           (math-expr-subst
  1525. X                        (math-expr-subst
  1526. X                         (math-expr-subst
  1527. X                          expr
  1528. X                          u
  1529. X                          math-integ-var-2)
  1530. X                         math-integ-var
  1531. X                         uinv)
  1532. X                        math-integ-var-2
  1533. X                        math-integ-var)
  1534. X                           deriv)
  1535. X                          'yes)))))
  1536. X     (math-simplify-extended
  1537. X      (math-expr-subst temp math-integ-var u))))
  1538. )
  1539. X
  1540. ;;; Look for substitutions of the form u = a x + b.
  1541. (defun math-integ-try-linear-substitutions (sub-expr)
  1542. X  (and (not (Math-primp sub-expr))
  1543. X       (or (and (not (memq (car sub-expr) '(+ - * / neg)))
  1544. X        (not (and (eq (car sub-expr) '^)
  1545. X              (integerp (nth 2 sub-expr))))
  1546. X        (math-expr-contains sub-expr math-integ-var)
  1547. X        (let ((res nil))
  1548. X          (while (and (setq sub-expr (cdr sub-expr))
  1549. X                  (or (not (math-linear-in (car sub-expr)
  1550. X                               math-integ-var))
  1551. X                  (assoc (car sub-expr) so-far)
  1552. X                  (progn
  1553. X                    (setq so-far (cons (list (car sub-expr))
  1554. X                               so-far))
  1555. X                    (not (setq res
  1556. X                           (math-integrate-by-substitution
  1557. X                        expr (car sub-expr))))))))
  1558. X          res))
  1559. X       (let ((res nil))
  1560. X         (while (and (setq sub-expr (cdr sub-expr))
  1561. X             (not (setq res (math-integ-try-linear-substitutions
  1562. X                     (car sub-expr))))))
  1563. X         res)))
  1564. )
  1565. X
  1566. ;;; Recursively try different substitutions based on various sub-expressions.
  1567. (defun math-integ-try-substitutions (sub-expr &optional allow-rat)
  1568. X  (and (not (Math-primp sub-expr))
  1569. X       (not (assoc sub-expr so-far))
  1570. X       (math-expr-contains sub-expr math-integ-var)
  1571. X       (or (and (if (and (not (memq (car sub-expr) '(+ - * / neg)))
  1572. X             (not (and (eq (car sub-expr) '^)
  1573. X                   (integerp (nth 2 sub-expr)))))
  1574. X            (prog1 allow-rat (setq allow-rat nil))
  1575. X          (setq allow-rat t))
  1576. X        (not (eq sub-expr expr))
  1577. X        (math-integrate-by-substitution expr sub-expr))
  1578. X       (let ((res nil))
  1579. X         (setq so-far (cons (list sub-expr) so-far))
  1580. X         (while (and (setq sub-expr (cdr sub-expr))
  1581. X             (not (setq res (math-integ-try-substitutions
  1582. X                     (car sub-expr) allow-rat)))))
  1583. X         res)))
  1584. )
  1585. X
  1586. (defun math-expr-rational-in (expr)
  1587. X  (let ((parts nil))
  1588. X    (math-expr-rational-in-rec expr)
  1589. X    (mapcar 'car parts))
  1590. )
  1591. X
  1592. (defun math-expr-rational-in-rec (expr)
  1593. X  (cond ((Math-primp expr)
  1594. X     (and (equal expr math-integ-var)
  1595. X          (not (assoc expr parts))
  1596. X          (setq parts (cons (list expr) parts))))
  1597. X    ((or (memq (car expr) '(+ - * / neg))
  1598. X         (and (eq (car expr) '^) (integerp (nth 2 expr))))
  1599. X     (math-expr-rational-in-rec (nth 1 expr))
  1600. X     (and (nth 2 expr) (math-expr-rational-in-rec (nth 2 expr))))
  1601. X    ((and (eq (car expr) '^)
  1602. X          (eq (math-quarter-integer (nth 2 expr)) 2))
  1603. X     (math-expr-rational-in-rec (list 'calcFunc-sqrt (nth 1 expr))))
  1604. X    (t
  1605. X     (and (not (assoc expr parts))
  1606. X          (math-expr-contains expr math-integ-var)
  1607. X          (setq parts (cons (list expr) parts)))))
  1608. )
  1609. X
  1610. (defun math-expr-calls (expr funcs &optional arg-contains)
  1611. X  (if (consp expr)
  1612. X      (if (or (memq (car expr) funcs)
  1613. X          (and (eq (car expr) '^) (eq (car funcs) 'calcFunc-sqrt)
  1614. X           (eq (math-quarter-integer (nth 2 expr)) 2)))
  1615. X      (and (or (not arg-contains)
  1616. X           (math-expr-contains expr arg-contains))
  1617. X           expr)
  1618. X    (and (not (Math-primp expr))
  1619. X         (let ((res nil))
  1620. X           (while (and (setq expr (cdr expr))
  1621. X               (not (setq res (math-expr-calls
  1622. X                       (car expr) funcs arg-contains)))))
  1623. X           res))))
  1624. )
  1625. X
  1626. (defun math-fix-const-terms (expr except-vars)
  1627. X  (cond ((not (math-expr-depends expr except-vars)) 0)
  1628. X    ((Math-primp expr) expr)
  1629. X    ((eq (car expr) '+)
  1630. X     (math-add (math-fix-const-terms (nth 1 expr) except-vars)
  1631. X           (math-fix-const-terms (nth 2 expr) except-vars)))
  1632. X    ((eq (car expr) '-)
  1633. X     (math-sub (math-fix-const-terms (nth 1 expr) except-vars)
  1634. X           (math-fix-const-terms (nth 2 expr) except-vars)))
  1635. X    (t expr))
  1636. )
  1637. X
  1638. ;; Command for debugging the Calculator's symbolic integrator.
  1639. (defun calc-dump-integral-cache (&optional arg)
  1640. X  (interactive "P")
  1641. X  (let ((buf (current-buffer)))
  1642. X    (unwind-protect
  1643. X    (let ((p math-integral-cache)
  1644. X          cur-record)
  1645. X      (display-buffer (get-buffer-create "*Integral Cache*")) 
  1646. X      (set-buffer (get-buffer "*Integral Cache*"))
  1647. X      (erase-buffer)
  1648. X      (while p
  1649. X        (setq cur-record (car p))
  1650. X        (or arg (math-replace-integral-parts cur-record))
  1651. X        (insert (math-format-flat-expr (car cur-record) 0)
  1652. X            " --> "
  1653. X            (if (symbolp (nth 1 cur-record))
  1654. X            (concat "(" (symbol-name (nth 1 cur-record)) ")")
  1655. X              (math-format-flat-expr (nth 1 cur-record) 0))
  1656. X            "\n")
  1657. X        (setq p (cdr p)))
  1658. X      (goto-char (point-min)))
  1659. X      (set-buffer buf)))
  1660. )
  1661. X
  1662. (defun math-try-integral (expr)
  1663. X  (let ((math-integ-level math-integral-limit)
  1664. X    (math-integ-depth 0)
  1665. X    (math-integ-msg "Working...done")
  1666. X    (cur-record nil)   ; a technicality
  1667. X    (math-integrating t)
  1668. X    (calc-prefer-frac t)
  1669. X    (calc-symbolic-mode t))
  1670. X    (or (math-integral expr 'yes)
  1671. X    (and math-any-substs
  1672. X         (setq math-enable-subst t)
  1673. X         (math-integral expr 'yes))
  1674. X    (and (> math-max-integral-limit math-integral-limit)
  1675. X         (setq math-integral-limit math-max-integral-limit
  1676. X           math-integ-level math-integral-limit)
  1677. X         (math-integral expr 'yes))))
  1678. )
  1679. X
  1680. (defun calcFunc-integ (expr var &optional low high)
  1681. X  (cond
  1682. X   ;; Do these even if the parts turn out not to be integrable.
  1683. X   ((eq (car-safe expr) '+)
  1684. X    (math-add (calcFunc-integ (nth 1 expr) var low high)
  1685. X          (calcFunc-integ (nth 2 expr) var low high)))
  1686. X   ((eq (car-safe expr) '-)
  1687. X    (math-sub (calcFunc-integ (nth 1 expr) var low high)
  1688. X          (calcFunc-integ (nth 2 expr) var low high)))
  1689. X   ((eq (car-safe expr) 'neg)
  1690. X    (math-neg (calcFunc-integ (nth 1 expr) var low high)))
  1691. X   ((and (eq (car-safe expr) '*)
  1692. X     (not (math-expr-contains (nth 1 expr) var)))
  1693. X    (math-mul (nth 1 expr) (calcFunc-integ (nth 2 expr) var low high)))
  1694. X   ((and (eq (car-safe expr) '*)
  1695. SHAR_EOF
  1696. true || echo 'restore of calc-alg-2.el failed'
  1697. fi
  1698. echo 'End of  part 4'
  1699. echo 'File calc-alg-2.el is continued in part 5'
  1700. echo 5 > _shar_seq_.tmp
  1701. exit 0
  1702. exit 0 # Just in case...
  1703. -- 
  1704. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1705. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1706. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1707. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1708.